using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace Super
{
	public class PanelManager : SimpleSingle<PanelManager>
	{
		public Dictionary<string, PanelBase> panelDict = new Dictionary<string, PanelBase>();
		public LinkedList<PanelBase> panelList = new LinkedList<PanelBase>();
		public override void OnInit()
		{
			base.OnInit();
			EventManager.Register<PanelOpenGE>(OnPanelOpen);
			EventManager.Register<PanelCloseGE>(OnPanelClose);
			SceneManager.sceneLoaded += OnSceneLoadFinish;
		}

		public void OnPanelOpen(PanelOpenGE eventData)
		{
			string panelName = eventData.panelName;
			PanelBase panelBase = eventData.panelBase;

			panelDict[panelName] = panelBase;
			if (panelList.Contains(panelBase))
			{
				panelList.Remove(panelBase);
				UpdatePanelList();
			}

			if (panelList.Last != null && panelList.Last.Value != panelBase)
			{
				panelBase.canvas.sortingOrder = panelList.Last.Value.canvas.sortingOrder + 1;
			}
			panelList.AddLast(panelBase);
		}
		

		public void OnPanelClose(PanelCloseGE eventData)
		{
			string panelName = eventData.panelName;
			PanelBase panelBase = panelDict[panelName];
			panelList.Remove(panelBase);
			UpdatePanelList();
		}

		public void OnSceneLoadFinish(Scene scene, LoadSceneMode mode)
		{

			ClearPanel();
			UpdatePanelList();
			UpdatePanelDict();
		}

		private void ClearPanel()
		{
			List<string> panelNames = new List<string>(panelDict.Keys);
			PanelBase tmpPanel;

			foreach (var panelName in panelNames)
			{
				if (panelDict.ContainsKey(panelName) && panelDict[panelName] != null)
				{
					tmpPanel = panelDict[panelName];
					if (!tmpPanel.gameObject.activeSelf)
					{
						GameObject.DestroyImmediate(tmpPanel.gameObject);
					}
				}
			}
		}
		private void UpdatePanelList()
		{
			LinkedListNode<PanelBase> node = panelList.First;
			int order = 0;
			while (node != null)
			{
				if (node.Value != null)
				{
					node.Value.canvas.sortingOrder = order++;
				}

				if (node.Previous != null && node.Previous.Value == null)
				{
					panelList.Remove(node.Previous);
				}
				node = node.Next;
			}
		}
		private void UpdatePanelDict()
		{
			List<string> panelNames = new List<string>(panelDict.Keys);
			foreach (var panelName in panelNames)
			{
				if (panelDict.ContainsKey(panelName) && panelDict[panelName] == null)
				{
					panelDict.Remove(panelName);
				}
			}
		}
		
		public static PanelBase FindPanel<T>() where T : PanelBase
		{
			string panelName = typeof(T).Name;
			return FindPanel(panelName);
		}

		public static PanelBase FindPanel(string panelName)
		{
			PanelBase panelBase = null;
			if (Ins.panelDict.ContainsKey(panelName))
			{
				panelBase = Ins.panelDict[panelName];
				if (panelBase == null)
				{
					Ins.panelDict.Remove(panelName);
				}
			}

			return panelBase;
		}

		public static bool CheckIfPanelVisible(string panelName)
		{
			PanelBase panelBase = FindPanel(panelName);
			if (panelBase != null && panelBase.gameObject.activeSelf)
			{
				return true;
			}
			return false;
		}

		public static bool CheckIfPanelVisible<T>() where T : PanelBase
		{
			string panelName = typeof(T).Name;
			return CheckIfPanelVisible(panelName);
		}
		
		public static void SetPanelBehind(PanelBase targetPanel, PanelBase behindPanel)
		{
			if (targetPanel == null && behindPanel == null) return;
			
			var behindNode = Ins.panelList.Find(behindPanel);
			var targetNode = Ins.panelList.Find(targetPanel);
			if (behindNode == null || targetNode == null) return;
			
			Ins.panelList.Remove(behindNode);
			Ins.panelList.AddBefore(targetNode, behindNode);
			Ins.UpdatePanelList();
		}
	}

}
